package com.othershe.behaviortest;

import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.ViewCompat;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import java.lang.ref.WeakReference;

/**
 * 支持触摸事件驱动的动态高度调整 Behavior，向下滑动时回弹，向上滑动时完全移除屏幕
 */
public class DynamicHeightBehavior extends AppBarLayout.Behavior {

    private WeakReference<View> targetViewRef;
    private int originalHeight = -1;
    private int minHeight = -1;
    private float lastTouchY;
    private boolean isHandlingTouch = false;
    private ValueAnimator reboundAnimator;
    private static final int TOUCH_SLOP = 5;
    private static final float OVERSCROLL_FACTOR = 0.4f;
    private boolean shouldRebound = false; // 标记是否需要回弹
    private boolean isClosed = false; // 标记header是否已完全关闭（移除屏幕）
    private WeakReference<View> scrollableViewRef; // 记录滚动视图

    public DynamicHeightBehavior() {
        super();
    }

    public DynamicHeightBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
        if (reboundAnimator != null && reboundAnimator.isRunning()) {
            reboundAnimator.cancel();
        }

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastTouchY = ev.getY();
                isHandlingTouch = false;
                shouldRebound = false;
                break;
            case MotionEvent.ACTION_MOVE:
                float deltaY = ev.getY() - lastTouchY;
                if (Math.abs(deltaY) > TOUCH_SLOP) {
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(parent, child, ev);
    }

    @Override
    public boolean onTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastTouchY = ev.getY();
                isHandlingTouch = false;
                shouldRebound = false;
                if (reboundAnimator != null && reboundAnimator.isRunning()) {
                    reboundAnimator.cancel();
                }
                return true;

            case MotionEvent.ACTION_MOVE:
                float deltaY = ev.getY() - lastTouchY;
                if (!isHandlingTouch && Math.abs(deltaY) > TOUCH_SLOP) {
                    isHandlingTouch = true;
                }

                if (isHandlingTouch) {
                    processTouchMovement(child, (int) deltaY);
                    lastTouchY = ev.getY();
                    // 只有向下滑动时标记需要回弹
                    if (deltaY > 0) {
                        shouldRebound = true;
                    }
                    return true;
                }
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (isHandlingTouch) {
                    isHandlingTouch = false;
                    // 仅在向下滑动时执行回弹
                    if (shouldRebound) {
                        performReboundAnimation(child);
                    }
                    return true;
                }
                break;
        }

        return super.onTouchEvent(parent, child, ev);
    }

    private void processTouchMovement(AppBarLayout appBarLayout, int deltaY) {
        View targetView = getTargetView(appBarLayout);
        if (targetView == null) return;

        initializeHeights(targetView);

        int currentHeight = targetView.getHeight();
        int adjustedDeltaY = deltaY;

        // 应用超越滚动阻力
        if ((deltaY > 0 && currentHeight >= originalHeight) ||
                (deltaY < 0 && currentHeight <= minHeight)) {
            adjustedDeltaY = (int) (deltaY * OVERSCROLL_FACTOR);
        }

        int newHeight = currentHeight + adjustedDeltaY;

        ViewGroup.LayoutParams params = targetView.getLayoutParams();
        params.height = newHeight;
        targetView.setLayoutParams(params);
    }

    private void performReboundAnimation(AppBarLayout appBarLayout) {
        View targetView = getTargetView(appBarLayout);
        if (targetView == null) return;

        int currentHeight = targetView.getHeight();
        if (currentHeight == originalHeight) return;

        if (reboundAnimator != null && reboundAnimator.isRunning()) {
            reboundAnimator.cancel();
        }

        reboundAnimator = ValueAnimator.ofInt(currentHeight, originalHeight);
        reboundAnimator.setDuration(300);
        reboundAnimator.addUpdateListener(animation -> {
            int animatedValue = (int) animation.getAnimatedValue();
            ViewGroup.LayoutParams params = targetView.getLayoutParams();
            params.height = animatedValue;
            targetView.setLayoutParams(params);
        });
        reboundAnimator.start();
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
        // 开始嵌套滚动时取消回弹动画
        if (reboundAnimator != null && reboundAnimator.isRunning()) {
            reboundAnimator.cancel();
        }
        
        // 记录滚动视图
        if (target instanceof RecyclerView || target instanceof NestedScrollView) {
            scrollableViewRef = new WeakReference<>(target);
        }
        
        return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout parent, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) {
        super.onNestedPreScroll(parent, child, target, dx, dy, consumed, type);

        View headerContainer = getTargetView(child);
        if (headerContainer == null) return;

        initializeHeights(headerContainer);

        // 查找需要动态调整的子View
        View fixedTitle = headerContainer.findViewById(R.id.fixed_title);
        View dynamicSubtitle1 = headerContainer.findViewById(R.id.dynamic_subtitle1);
        View dynamicSubtitle2 = headerContainer.findViewById(R.id.dynamic_subtitle2);

        if (fixedTitle == null || dynamicSubtitle1 == null || dynamicSubtitle2 == null) return;

        // 向上滑动 (dy > 0) 且 header 未完全关闭
        if (dy > 0 && !isClosed) {
            int currentHeight = headerContainer.getHeight();
            int newHeight = currentHeight - dy;

            if (newHeight <= 0) {
                // 完全关闭header
                newHeight = 0;
                isClosed = true;
            }

            // 更新header高度
            ViewGroup.LayoutParams params = headerContainer.getLayoutParams();
            params.height = newHeight;
            headerContainer.setLayoutParams(params);

            // 根据高度动态调整子View
            adjustChildViews(newHeight, originalHeight, fixedTitle, dynamicSubtitle1, dynamicSubtitle2);

            consumed[1] = dy;
        }
        // 向下滑动 (dy < 0) 且 header 已完全关闭或者还可以展开
        else if (dy < 0) {
            if (isClosed) {
                // 重置header高度并标记为未关闭
                ViewGroup.LayoutParams params = headerContainer.getLayoutParams();
                params.height = Math.min(-dy, originalHeight);
                headerContainer.setLayoutParams(params);
                isClosed = false;

                // 调整子View
                adjustChildViews(params.height, originalHeight, fixedTitle, dynamicSubtitle1, dynamicSubtitle2);

                consumed[1] = Math.abs(dy);
            } else {
                // header未完全关闭但还可以展开
                int currentHeight = headerContainer.getHeight();
                int newHeight = currentHeight - dy; // dy为负，相当于增加高度

                if (newHeight > originalHeight) {
                    newHeight = originalHeight;
                }

                // 更新header高度
                ViewGroup.LayoutParams params = headerContainer.getLayoutParams();
                params.height = newHeight;
                headerContainer.setLayoutParams(params);

                // 调整子View
                adjustChildViews(newHeight, originalHeight, fixedTitle, dynamicSubtitle1, dynamicSubtitle2);

                consumed[1] = Math.abs(dy);
            }
        }
    }

    /**
     * 根据当前高度调整子View的显示状态
     * @param currentHeight 当前header高度
     * @param originalHeight 原始header高度
     * @param fixedTitle 固定显示的标题
     * @param dynamicSubtitle1 动态副标题1
     * @param dynamicSubtitle2 动态副标题2
     */
    private void adjustChildViews(int currentHeight, int originalHeight,
                                  View fixedTitle, View dynamicSubtitle1, View dynamicSubtitle2) {
        if (currentHeight <= 0) {
            // 完全隐藏所有动态View
            dynamicSubtitle1.setVisibility(View.GONE);
            dynamicSubtitle2.setVisibility(View.GONE);
            return;
        }

        // 固定标题始终显示
        fixedTitle.setVisibility(View.VISIBLE);

        // 根据高度比例显示动态View
        float heightRatio = (float) currentHeight / originalHeight;

        if (heightRatio >= 0.7f) {
            // 高度足够时显示所有View
            dynamicSubtitle1.setVisibility(View.VISIBLE);
            dynamicSubtitle2.setVisibility(View.VISIBLE);

            // 可以根据需要调整View的高度或透明度
            ViewGroup.LayoutParams params1 = dynamicSubtitle1.getLayoutParams();
            params1.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            dynamicSubtitle1.setLayoutParams(params1);

            ViewGroup.LayoutParams params2 = dynamicSubtitle2.getLayoutParams();
            params2.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            dynamicSubtitle2.setLayoutParams(params2);
        } else if (heightRatio >= 0.4f) {
            // 中等高度时只显示第一个动态View
            dynamicSubtitle1.setVisibility(View.VISIBLE);
            dynamicSubtitle2.setVisibility(View.GONE);

            // 可以根据需要调整View的高度
            ViewGroup.LayoutParams params1 = dynamicSubtitle1.getLayoutParams();
            params1.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            dynamicSubtitle1.setLayoutParams(params1);
        } else {
            // 高度较小时隐藏所有动态View
            dynamicSubtitle1.setVisibility(View.GONE);
            dynamicSubtitle2.setVisibility(View.GONE);
        }
    }

    @Override
    public void onStopNestedScroll(CoordinatorLayout parent, AppBarLayout child, View target, int type) {
        super.onStopNestedScroll(parent, child, target, type);
        
        // 停止滚动时，如果header已完全关闭，则不需要任何操作
        if (isClosed) {
            return;
        }
        
        // 这里可以添加其他必要的逻辑
    }

    private View getTargetView(AppBarLayout appBarLayout) {
        if (targetViewRef != null) {
            View view = targetViewRef.get();
            if (view != null) {
                return view;
            }
        }

        for (int i = 0; i < appBarLayout.getChildCount(); i++) {
            View child = appBarLayout.getChildAt(i);
            if ("dynamic_height_view".equals(child.getTag())) {
                targetViewRef = new WeakReference<>(child);
                return child;
            }
        }

        return null;
    }

    private void initializeHeights(View targetView) {
        if (originalHeight == -1) {
            originalHeight = targetView.getHeight();
            minHeight = Math.max(targetView.getMinimumHeight(), originalHeight / 3);
        }
    }

    @Override
    public void onDetachedFromLayoutParams() {
        super.onDetachedFromLayoutParams();
        if (reboundAnimator != null) {
            reboundAnimator.cancel();
            reboundAnimator = null;
        }
    }
}